﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using WeDonekRpc.Modular.SysEvent.Model;
using WeDonekRpc.Client;
using WeDonekRpc.Client.Interface;
using WeDonekRpc.Helper;
using WeDonekRpc.ModularModel.SysEvent;
using WeDonekRpc.ModularModel.SysEvent.Model;
using WeDonekRpc.ModularModel.SysEvent.Msg;

namespace WeDonekRpc.Modular.SysEvent
{
    internal class RpcEventService : IRpcEventService
    {
        private static IDelayDataSave<SysEventLog> _Logs;
        private static readonly ConcurrentDictionary<string, IRpcEventModule> _Modules = new ConcurrentDictionary<string, IRpcEventModule>();
        private static IRpcService _RpcService;

        private static IRpcEventService _CurService;
        private static void _Refresh (RefreshEventModule data)
        {
            if (_Modules.TryRemove(data.Module, out IRpcEventModule module))
            {
                module.Dispose();
            }
            ServiceSysEvent[] list = new GetEnableSysEvent
            {
                Module = data.Module
            }.Send();
            if (!list.IsNull())
            {
                _AddModule(data.Module, list);
            }
            if (_Modules.Count == 0 && _Logs != null)
            {
                _Logs.Dispose();
                _Logs = null;
            }
            else if (_Modules.Count != 0 && _Logs == null)
            {
                _Logs = new DelayDataSave<SysEventLog>(_SaveLogs, 2, 10);
            }
        }

        private static void _SaveLogs (ref SysEventLog[] datas)
        {
            new AddSysEventLog
            {
                Logs = datas
            }.Send();
        }

        public void AddLog (BasicEvent ev, Dictionary<string, string> args)
        {
            _Logs.AddData(new SysEventLog
            {
                CreateTime = DateTime.Now,
                EventId = ev.EventId,
                Attrs = args
            });
        }
        public void AddLog (long evId, Dictionary<string, string> args)
        {
            _Logs.AddData(new SysEventLog
            {
                CreateTime = DateTime.Now,
                EventId = evId,
                Attrs = args
            });
        }

        public void Init (IRpcService service)
        {
            _CurService = this;
            _RpcService = service;
            RpcClient.Route.AddRoute<RefreshEventModule>(_Refresh);
            service.Closing += this.Service_Closing;
            service.StartUpComplating += this.Service_BeginIniting;
        }
        private static void _AddModule (string name, ServiceSysEvent[] evs)
        {
            IRpcEventModule module;
            if (name == "RpcSendBehavior")
            {
                module = new Module.RpcSendBehaviorModule(evs, _CurService, _RpcService);
            }
            else if (name == "CpuBehavior")
            {
                module = new Module.CpuBehaviorModule(evs, _CurService);
            }
            else if (name == "MemoryOccupation")
            {
                module = new Module.MemoryOccupationModule(evs, _CurService);
            }
            else if (name == "RpcReplyBehavior")
            {
                module = new Module.RpcReplyBehaviorModule(evs, _CurService, _RpcService);
            }
            else if (name == "RemoteStateChange")
            {
                module = new Module.RemoteStateChangeModule(evs, _CurService, _RpcService);
            }
            else if (name == "NoServerError")
            {
                module = new Module.NoServerErrorModule(evs, _CurService, _RpcService);
            }
            else
            {
                return;
            }
            if (_Modules.TryAdd(name, module))
            {
                module.Init();
            }
        }
        private void Service_BeginIniting ()
        {
            ServiceSysEvent[] list = new GetEnableSysEvent().Send();
            if (list.IsNull())
            {
                return;
            }
            _Logs = new DelayDataSave<SysEventLog>(_SaveLogs, 2, 10);
            string[] module = list.Distinct(a => a.Module);
            module.ForEach(a =>
            {
                ServiceSysEvent[] evs = list.FindAll(c => c.Module == a);
                _AddModule(a, evs);
            });
        }

        private void Service_Closing ()
        {
            _Logs?.Dispose();
            if (_Modules.Count > 0)
            {
                foreach (KeyValuePair<string, IRpcEventModule> item in _Modules)
                {
                    item.Value.Dispose();
                }
            }
        }
    }
}
